package com.hhd.pdf.component;

import com.hhd.pdf.CommonUtils;
import com.hhd.pdf.component.branch.HasBranch;
import com.hhd.pdf.context.GeneratorContext;
import com.hhd.pdf.utils.PdfUtils;
import com.hhd.pdf.variable.CompositeFormula;
import com.hhd.pdf.variable.VariableContext;
import com.itextpdf.text.Element;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfDiv;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Node;
import org.dom4j.tree.DefaultComment;
import org.dom4j.tree.DefaultText;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.util.List;

@Slf4j
public abstract class AbstractPdfComponent implements PdfComponent {

    @Lazy
    @Autowired
    protected PdfComponentDelegate componentDelegate;

    @Override
    public List<Element> genElements(GeneratorContext context) {
        org.dom4j.Element parsingElement = context.getRuntimeData().getParsingElement();
        PdfDiv div = new PdfDiv();
        List<Element> res = doGenElements(context);

        resolvePadding(div, parsingElement);
        if (!CommonUtils.isEmpty(res)) {
            res.forEach(div::addElement);
        }
        return CommonUtils.newList(div);
    }

    private void resolvePadding(PdfDiv div, org.dom4j.Element parsingElement) {
        String paddingLeft = parsingElement.attributeValue("paddingLeft");
        String paddingRight = parsingElement.attributeValue("paddingRight");
        String paddingBottom = parsingElement.attributeValue("paddingBottom");
        String paddingTop = parsingElement.attributeValue("paddingTop");

        try {
            if (!CommonUtils.isEmpty(paddingLeft)) {
                div.setPaddingLeft(Integer.parseInt(paddingLeft));
            }
            if (!CommonUtils.isEmpty(paddingRight)) {
                div.setPaddingRight(Integer.parseInt(paddingRight));
            }
            if (!CommonUtils.isEmpty(paddingBottom)) {
                div.setPaddingBottom(Integer.parseInt(paddingBottom));
            }
            if (!CommonUtils.isEmpty(paddingTop)) {
                div.setPaddingTop(Integer.parseInt(paddingTop));
            }
        } catch (Exception e) {
            log.warn(e.getMessage(), e);
        }
    }

    protected List<Element> genChildren(GeneratorContext context, org.dom4j.Element element) {

        if(!has(element, context)) return CommonUtils.newList();
        int count = element.nodeCount();
        List<Element> res = CommonUtils.newList();
        for (int i = 0; i < count; i++) {
            Node node = element.node(i);
            if (node instanceof DefaultText) {
                List<Element> elements = componentDelegate.genElementText((DefaultText) node, context);
                if (!CommonUtils.isEmpty(elements)) {
                    res.addAll(elements);
                }
            } else if (node instanceof DefaultComment) {
                continue;
            } else {
                org.dom4j.Element childrenElement = (org.dom4j.Element) node;
                if (!has(childrenElement, context)) continue;
                GeneratorContext childrenContext = context.runtime(childrenElement);
                resolveParametersConfig(childrenContext, element);
                List<Element> elements = componentDelegate.genElements(childrenContext);
                if (!CommonUtils.isEmpty(elements)) {
                    res.addAll(elements);
                }
            }
        }

        return wrapIfPhrase(res, element, context);
    }

    protected boolean has(org.dom4j.Element childrenElement, GeneratorContext context) {
        return HasBranch.has(childrenElement, context.getVariableContext());
    }


    private List<Element> wrapIfPhrase(List<Element> res, org.dom4j.Element parentElement, GeneratorContext context) {
        if (CommonUtils.isEmpty(res)) return res;
        for (Element e : res) {
            if (!PdfUtils.isPhrase(e)) {
                return res;
            }
        }
        return CommonUtils.newList(createParagraph(res, parentElement, context));
    }

    private Paragraph createParagraph(List<Element> res, org.dom4j.Element parentElement, GeneratorContext context) {
        Paragraph paragraph = PdfUtils.createParagraph();
        resolveAlign(parentElement, paragraph, context);
        paragraph.addAll(res);
        return paragraph;
    }

    private void resolveAlign(org.dom4j.Element element, Paragraph paragraph, GeneratorContext context) {
        paragraph.setAlignment(context.getGeneratorParameters().getAlign());
        String align = element.attributeValue("align");
        if (CommonUtils.isEmpty(align)) return;
        if ("left".equals(align)) {
            paragraph.setAlignment(Element.ALIGN_LEFT);
        }
        if ("right".equals(align)) {
            paragraph.setAlignment(Element.ALIGN_RIGHT);
        }
        if ("center".equals(align)) {
            paragraph.setAlignment(Element.ALIGN_CENTER);
        }
    }

    protected void setDefaultAttribute(org.dom4j.Element element, String key, String value) {
        if (CommonUtils.isEmpty(element.attributeValue(key))) {
            element.addAttribute(key, value);
        }
    }

    private void resolveParametersConfig(GeneratorContext childrenContext, org.dom4j.Element element) {

    }

    public abstract List<Element> doGenElements(GeneratorContext context);

    protected CompositeFormula executeFormula(String formulaText, GeneratorContext context) {
        VariableContext variableContext = context.getVariableContext();
        CompositeFormula formula = CompositeFormula.formula(formulaText);
        formula.execute(variableContext);
        return formula;
    }
}
